#include "GY_GraphicsEllipseItem.h"
#include <QPen>
#include <QPainter>
#include <QDebug>

GY_GraphicsEllipseItem::GY_GraphicsEllipseItem(const QString &guid,QGraphicsItem *parent)
    :GY_BasicsGraphicsObject(guid,this,parent)
{
    //图元类型
    GY_Object::setUserData(GY_ENUM::ClassType,QVariant("EllipseItem"));
    initializationPropertyInfo();
    updataPen();
    updataBrush();
    QPointF point1=m_PropertyInfoMap.value("Point1").propertyValue.value<QPointF>();
    QPointF point2=m_PropertyInfoMap.value("Point2").propertyValue.value<QPointF>();
    QPointF point3=m_PropertyInfoMap.value("Point3").propertyValue.value<QPointF>();
    updatePath(point1,point2,point3);
    QMap<QVariant,QPointF> editPoints = {{"Point1",point1},{"Point2",point2},{"Point3",point3}};
    this->setPen(QColor(Qt::green));
    this->setEditPointF(editPoints);
    this->setCenterPointF(m_PropertyInfoMap["Center"].propertyValue.toPointF());
}

GY_GraphicsEllipseItem::GY_GraphicsEllipseItem(const QString &guid,qreal x, qreal y, qreal w, qreal h, QGraphicsItem *parent)
    :GY_BasicsGraphicsObject(guid,this,parent)
{
    //图元类型
    GY_Object::setUserData(GY_ENUM::ClassType,QVariant("EllipseItem"));
    initializationPropertyInfo();
    updataPen();
    updataBrush();
    QPointF point1(x+w/2,y+h);
    QPointF point2(x+w,y+h);
    QPointF point3(x+w,y+h/2);
    m_PropertyInfoMap["Point1"].propertyValue=point1;
    m_PropertyInfoMap["Point2"].propertyValue=point2;
    m_PropertyInfoMap["Point3"].propertyValue=point3;
    m_PropertyInfoMap["RadiusX"].propertyValue=w/2;
    m_PropertyInfoMap["RadiusY"].propertyValue=h/2;
    updatePath(point1,point2,point3);
    QMap<QVariant,QPointF> editPoints = {{"Point1",point1},{"Point2",point2},{"Point3",point3}};
    this->setEditPointF(editPoints);
    QPointF Position(x+w/2,y+h/2);
    this->setCenterPointF(Position);
    m_PropertyInfoMap["Center"].propertyValue = Position;
}
/**
 * @brief initializationPropertyInfo 初始化属性信息
 */
void GY_GraphicsEllipseItem::initializationPropertyInfo()
{
    /*
     *LineStyle属性的数据
     * QVector<qreal>中index(0)是Qt::PenCapStyle、Qt::PenJoinStyle与Qt::PenStyle的组合,index(1)为线条粗细，之后是自定义钢笔样式的数据 */
    QVector<qreal> varStyle;
    int style = Qt::SquareCap|Qt::BevelJoin|Qt::CustomDashLine;
    varStyle<<style<<2<<3<<2<<4<<5<<6<<7;

    int gradientSpread = QGradient::PadSpread;//指定如何填充渐变之外的区域
    QColor colorStart = QColor(0,255,0);//开始颜色
    QColor colorStop = QColor(0,0,255);//结束颜色
    int gradientType = QGradient::LinearGradient;//指定渐变的类型
    QPointF pointFStart = QPointF(0,0);//开始的坐标或中心点坐标
    QPointF pointFStop = QPointF(1,1);//结束的坐标或径向梯度的焦点坐标
    qreal centerRadius = 100;//中心半径
    qreal focalRadius = 100;//径向梯度的焦点半径
    QVector<qreal> varGradientStyle;
    varGradientStyle<<gradientSpread<<colorStart.rgb()<<colorStop.rgb()<<gradientType<<pointFStart.x()
                   <<pointFStart.y()<<pointFStop.x()<<pointFStop.y()<<centerRadius<<focalRadius;

    //位置
    GY_PropertyInfo positonPropertyInfo(this);
    positonPropertyInfo.propertyName="Center";
    positonPropertyInfo.propertyValue=QPointF(0,0);
    positonPropertyInfo.updateType = Update|MoveUpdate|PointOfRelative;
    positonPropertyInfo.propertyType = PointPropertyType;
    positonPropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsEllipseItem::updateCirlePoint;
    m_PropertyInfoMap.insert(positonPropertyInfo.propertyName,positonPropertyInfo);
    m_PropertyInfoMap[positonPropertyInfo.propertyName].setConnect();

    GY_PropertyInfo point1PropertyInfo(this);
    point1PropertyInfo.propertyName="Point1";
    point1PropertyInfo.propertyValue=QPointF(0,50);
    point1PropertyInfo.updateType = NotUpdate;
    point1PropertyInfo.propertyType = PointPropertyType;
    point1PropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsEllipseItem::updatePoint;
    m_PropertyInfoMap.insert("Point1",point1PropertyInfo);
    m_PropertyInfoMap[point1PropertyInfo.propertyName].setConnect();

    GY_PropertyInfo point2PropertyInfo(this);
    point2PropertyInfo.propertyName="Point2";
    point2PropertyInfo.propertyValue=QPointF(50,50);
    point2PropertyInfo.updateType = NotUpdate;
    point2PropertyInfo.propertyType = PointPropertyType;
    point2PropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsEllipseItem::updatePoint;
    m_PropertyInfoMap.insert("Point2",point2PropertyInfo);
    m_PropertyInfoMap[point2PropertyInfo.propertyName].setConnect();

    GY_PropertyInfo point3PropertyInfo(this);
    point3PropertyInfo.propertyName="Point3";
    point3PropertyInfo.propertyValue=QPointF(50,0);
    point3PropertyInfo.updateType = NotUpdate;
    point3PropertyInfo.propertyType = PointPropertyType;
    point3PropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsEllipseItem::updatePoint;
    m_PropertyInfoMap.insert("Point3",point3PropertyInfo);
    m_PropertyInfoMap[point3PropertyInfo.propertyName].setConnect();

    GY_PropertyInfo radiusXPropertyInfo(this);
    radiusXPropertyInfo.propertyName="RadiusX";
    radiusXPropertyInfo.propertyValue=50.0;
    radiusXPropertyInfo.updateType = Update|OrdinaryAttributes;
    radiusXPropertyInfo.propertyType = DoublePropertyType;
    radiusXPropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsEllipseItem::updateRadiusX;
    m_PropertyInfoMap.insert(radiusXPropertyInfo.propertyName,radiusXPropertyInfo);
    m_PropertyInfoMap[radiusXPropertyInfo.propertyName].setConnect();

    GY_PropertyInfo radiusYPropertyInfo(this);
    radiusYPropertyInfo.propertyName="RadiusY";
    radiusYPropertyInfo.propertyValue=50.0;
    radiusYPropertyInfo.updateType = Update|OrdinaryAttributes;
    radiusYPropertyInfo.propertyType = DoublePropertyType;
    radiusYPropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsEllipseItem::updateRadiusY;
    m_PropertyInfoMap.insert(radiusYPropertyInfo.propertyName,radiusYPropertyInfo);
    m_PropertyInfoMap[radiusYPropertyInfo.propertyName].setConnect();

    GY_PropertyInfo ObjectName(this);
    ObjectName.propertyName = "ObjectName";
    ObjectName.propertyValue = QString();
    ObjectName.updateType = Update|OrdinaryAttributes;
    ObjectName.propertyType = QStringPropertyType;
    ObjectName.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsEllipseItem::updateObjectName;
    m_PropertyInfoMap.insert("ObjectName",ObjectName);
    m_PropertyInfoMap[ObjectName.propertyName].setConnect();

    GY_PropertyInfo IsOutLined(this);
    IsOutLined.propertyName = "IsOutlined";
    IsOutLined.propertyValue = true;
    IsOutLined.updateType = Update|OrdinaryAttributes;
    IsOutLined.propertyType = BoolPropertyType;
    IsOutLined.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsEllipseItem::updateIsOutLined;
    m_PropertyInfoMap.insert("IsOutlined",IsOutLined);
    m_PropertyInfoMap[IsOutLined.propertyName].setConnect();

    GY_PropertyInfo IsFilled(this);
    IsFilled.propertyName = "IsFilled";
    IsFilled.propertyValue = true;
    IsFilled.updateType = Update|OrdinaryAttributes;
    IsFilled.propertyType = BoolPropertyType;
    IsFilled.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsEllipseItem::updateIsFilled;
    m_PropertyInfoMap.insert("IsFilled",IsFilled);
    m_PropertyInfoMap[IsFilled.propertyName].setConnect();

    GY_PropertyInfo IsAntialiased(this);
    IsAntialiased.propertyName = "IsAntialiased";
    IsAntialiased.propertyValue = false;
    IsAntialiased.updateType = Update|OrdinaryAttributes;
    IsAntialiased.propertyType = BoolPropertyType;
    IsAntialiased.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsEllipseItem::updateIsAntialiased;
    m_PropertyInfoMap.insert("IsAntialiased",IsAntialiased);
    m_PropertyInfoMap[IsAntialiased.propertyName].setConnect();

    GY_PropertyInfo FillAttributes(this);
    FillAttributes.propertyName = "FillAttributes";
    FillAttributes.propertyValue = false;
    FillAttributes.updateType = Update|OrdinaryAttributes;
    FillAttributes.propertyType = BoolPropertyType;
    FillAttributes.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsEllipseItem::updateFillAttributes;
    m_PropertyInfoMap.insert("FillAttributes",FillAttributes);
    m_PropertyInfoMap[FillAttributes.propertyName].setConnect();

    GY_PropertyInfo FillGradient(this);
    FillGradient.propertyName = "FillGradient";
    FillGradient.propertyValue = QVariant::fromValue(varGradientStyle);
    FillGradient.updateType = Update|OrdinaryAttributes;
    FillGradient.propertyType = FillGradientPropertyType;
    FillGradient.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsEllipseItem::updateFillGradient;
    m_PropertyInfoMap.insert("FillGradient",FillGradient);
    m_PropertyInfoMap[FillGradient.propertyName].setConnect();

    GY_PropertyInfo FillColor(this);
    FillColor.propertyName = "FillColor";
    FillColor.propertyValue = QColor();
    FillColor.updateType = Update|OrdinaryAttributes;
    FillColor.propertyType = ColorPropertyType;
    FillColor.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsEllipseItem::updateFillColor;
    m_PropertyInfoMap.insert("FillColor",FillColor);
    m_PropertyInfoMap[FillColor.propertyName].setConnect();

    GY_PropertyInfo FillStyle(this);
    FillStyle.propertyName = "FillStyle";
    FillStyle.propertyValue = true;
    FillStyle.updateType = Update|OrdinaryAttributes;
    FillStyle.propertyType = FillStylePropertyType;
    FillStyle.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsEllipseItem::updateFillStyle;
    m_PropertyInfoMap.insert("FillStyle",FillStyle);
    m_PropertyInfoMap[FillStyle.propertyName].setConnect();

    GY_PropertyInfo PenColor(this);
    PenColor.propertyName = "PenColor";
    PenColor.propertyValue = QColor();
    PenColor.updateType = Update|OrdinaryAttributes;
    PenColor.propertyType = ColorPropertyType;
    PenColor.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsEllipseItem::updatePenColor;
    m_PropertyInfoMap.insert("PenColor",PenColor);
    m_PropertyInfoMap[PenColor.propertyName].setConnect();

    GY_PropertyInfo PenAttributes(this);
    PenAttributes.propertyName = "PenAttributes";
    PenAttributes.propertyValue = false;
    PenAttributes.updateType = Update|OrdinaryAttributes;
    PenAttributes.propertyType = BoolPropertyType;
    PenAttributes.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsEllipseItem::updatePenAttributes;
    m_PropertyInfoMap.insert("PenAttributes",PenAttributes);
    m_PropertyInfoMap[PenAttributes.propertyName].setConnect();

    GY_PropertyInfo FillOpacity(this);
    FillOpacity.propertyName = "FillOpacity";
    FillOpacity.propertyValue = 1;
    FillOpacity.updateType = Update|OrdinaryAttributes;
    FillOpacity.propertyType = QrealPropertyType;
    FillOpacity.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsEllipseItem::updateFillOpacity;
    m_PropertyInfoMap.insert("FillOpacity",FillOpacity);
    m_PropertyInfoMap[FillOpacity.propertyName].setConnect();

    //Pattern填充图案数据
    QVector<QPoint> points;
    points << QPoint(0,1)<< QPoint(2,1)<< QPoint(3,1) << QPoint(5,1)<< QPoint(5,15) << QPoint(14,8);
    GY_PropertyInfo Pattern(this);
    Pattern.propertyName = "Pattern";
//    Pattern.propertyValue = QVariant::fromValue(points);
    Pattern.propertyValue = QVariant();
    Pattern.updateType = Update|OrdinaryAttributes;
    Pattern.propertyType = PatternPropertyType;
    Pattern.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsEllipseItem::updatePattern;
    m_PropertyInfoMap.insert("Pattern",Pattern);
    m_PropertyInfoMap[Pattern.propertyName].setConnect();

    GY_PropertyInfo PenOpacity(this);
    PenOpacity.propertyName = "PenOpacity";
    PenOpacity.propertyValue = 1;
    PenOpacity.updateType = Update|OrdinaryAttributes;
    PenOpacity.propertyType = QrealPropertyType;
    PenOpacity.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsEllipseItem::updatePenOpacity;
    m_PropertyInfoMap.insert("PenOpacity",PenOpacity);
    m_PropertyInfoMap[PenOpacity.propertyName].setConnect();

    GY_PropertyInfo LineStyle(this);
    LineStyle.propertyName = "LineStyle";
//    LineStyle.propertyValue = QVariant::fromValue(varStyle);
    LineStyle.propertyValue = QVariant();
    LineStyle.updateType = Update|OrdinaryAttributes;
    LineStyle.propertyType = LineStylePropertyType;
    LineStyle.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsEllipseItem::updateLineStyle;
    m_PropertyInfoMap.insert("LineStyle",LineStyle);
    m_PropertyInfoMap[LineStyle.propertyName].setConnect();

    GY_PropertyInfo IsVisible(this);
    IsVisible.propertyName = "IsVisible";
    IsVisible.propertyValue = true;
    IsVisible.updateType = Update|OrdinaryAttributes;
    IsVisible.propertyType = BoolPropertyType;
    IsVisible.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsEllipseItem::updateIsVisible;
    m_PropertyInfoMap.insert("IsVisible",IsVisible);
    m_PropertyInfoMap[IsVisible.propertyName].setConnect();

}

bool GY_GraphicsEllipseItem::updateCirlePoint(const QString &name, const QVariant &value)
{
    if(!value.canConvert<QPointF>())
    {
        return false;
    }
    QPointF point1=m_PropertyInfoMap.value("Point1").propertyValue.value<QPointF>();
    QPointF point2=m_PropertyInfoMap.value("Point2").propertyValue.value<QPointF>();
    QPointF point3=m_PropertyInfoMap.value("Point3").propertyValue.value<QPointF>();
    QPointF position = this->mapFromScene(value.toPointF());
    m_PropertyInfoMap[name].propertyValue=position;
    this->setCenterPointF(position);
    point1.setX(position.x());
    point1.setY(position.y()+m_PropertyInfoMap["RadiusY"].propertyValue.toDouble());
    point2.setX(position.x()+m_PropertyInfoMap["RadiusX"].propertyValue.toDouble());
    point2.setY(position.y()+m_PropertyInfoMap["RadiusY"].propertyValue.toDouble());
    point3.setX(position.x()+m_PropertyInfoMap["RadiusX"].propertyValue.toDouble());
    point3.setY(position.y());
    updatePath(point1,point2,point3);
    QMap<QVariant,QPointF> editPoints = {{"Point1",point1},{"Point2",point2},{"Point3",point3}};
    this->setEditPointF(editPoints);
    return true;
}

void GY_GraphicsEllipseItem::updatePath(const QPointF &point1, const QPointF &point2, const QPointF &point3)
{
    qreal w = 2*(point3.x() - point1.x());
    qreal h = 2*(point1.y() - point3.y());
    QPainterPath path = this->path();
    path.clear();
    path.addEllipse(point2.x() - w,point2.y() - h,w,h);
    this->setPath(path);
}


bool GY_GraphicsEllipseItem::updatePoint(const QString &name,const QVariant &value)
{
    if(!value.canConvert<QPointF>())
    {
        return false;
    }
    QPointF  pointf=value.value<QPointF>();
    //坐标系转换（重要）
    QPointF pf = this->mapFromScene(pointf);
    QMap<QVariant,QPointF> map = this->getEditPointF();
    QPointF point1 = map.value("Point1");
    QPointF point2 = map.value("Point2");
    QPointF point3 = map.value("Point3");
    //根据编辑点名称对应修改的点
    if(name.endsWith("Point1")){
        point1.setY(pf.y());
        map.insert("Point1",point1);
        m_PropertyInfoMap["Point1"].propertyValue=point1;
        point2.setY(pf.y());
        map.insert("Point2",point2);
        m_PropertyInfoMap["Point2"].propertyValue=point2;
        m_PropertyInfoMap["RadiusY"].propertyValue=point2.y()-point3.y();
        updatePath(point1,point2,point3);
    }else if(name.endsWith("Point2")){
        point2.setX(pf.x());
        point2.setY(pf.y());
        map.insert("Point2",point2);
        m_PropertyInfoMap["Point2"].propertyValue=point2;
        point1.setY(pf.y());
        map.insert("Point1",point1);
        m_PropertyInfoMap["Point1"].propertyValue=point1;
        point3.setX(pf.x());
        map.insert("Point3",point3);
        m_PropertyInfoMap["Point3"].propertyValue=point3;
        m_PropertyInfoMap["RadiusX"].propertyValue=point3.x()-point1.x();
        m_PropertyInfoMap["RadiusY"].propertyValue=point1.y()-point3.y();
        updatePath(point1,point2,point3);
    }else if(name.endsWith("Point3")){
        point3.setX(pf.x());
        map.insert("Point3",point3);
        m_PropertyInfoMap["Point3"].propertyValue=point3;
        point2.setX(pf.x());
        map.insert("Point2",point2);
        m_PropertyInfoMap["Point2"].propertyValue=point2;
        m_PropertyInfoMap["RadiusX"].propertyValue=point3.x()-point1.x();
        updatePath(point1,point2,point3);
    }
    this->setEditPointF(map);
    return true;
}

bool GY_GraphicsEllipseItem::updateRadiusX(const QString &name, const QVariant &value)
{
    if(!value.canConvert<double>())
    {
        return false;
    }
    QPointF center = m_PropertyInfoMap["Center"].propertyValue.toPointF();
    m_PropertyInfoMap[name].propertyValue=value;
    QMap<QVariant,QPointF> map = this->getEditPointF();
    QPointF point1 = map.value("Point1");
    QPointF point2 = map.value("Point2");
    QPointF point3 = map.value("Point3");
    point2.setX(center.x()+value.toReal());
    point3.setX(center.x()+value.toReal());
    m_PropertyInfoMap["Point2"].propertyValue=point2;
    m_PropertyInfoMap["Point3"].propertyValue=point3;
    map.insert("Point2",point2);
    map.insert("Point3",point3);
    this->setEditPointF(map);
    updatePath(point1,point2,point3);
    return true;
}

bool GY_GraphicsEllipseItem::updateRadiusY(const QString &name, const QVariant &value)
{
    if(!value.canConvert<double>())
    {
        return false;
    }
    QPointF center = m_PropertyInfoMap["Center"].propertyValue.toPointF();
    m_PropertyInfoMap[name].propertyValue=value;
    QMap<QVariant,QPointF> map = this->getEditPointF();
    QPointF point1 = map.value("Point1");
    QPointF point2 = map.value("Point2");
    QPointF point3 = map.value("Point3");
    point2.setY(center.y()+value.toReal());
    point1.setY(center.y()+value.toReal());
    m_PropertyInfoMap["Point2"].propertyValue=point2;
    m_PropertyInfoMap["Point"].propertyValue=point1;
    map.insert("Point2",point2);
    map.insert("Point1",point1);
    this->setEditPointF(map);
    updatePath(point1,point2,point3);
    return true;
}
